package com.birdcage.goldminer.gameobjects;

import android.util.Log;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.math.Vector2;
import com.birdcage.gamemanagers.GameObject;
import com.birdcage.gamemanagers.GameObjectManager;
import com.birdcage.gamemanagers.PhysicsElement;
import com.birdcage.gamemanagers.ResourceManager;

public final class Hook extends GameObject
{
    private Vector2 m_rotateOrigin = new Vector2(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/6*5+20);
    private float m_rotateRadius = 30.0f;
    private float m_maxDegree = 60.0f;
    private float m_rotateSpeed = 100.0f;
    private float m_currentDegree = 0;
    private int m_curRotateDirFactor = 1;
    private float m_ejectSpeed = 500.f;
    private float m_ejectLength = 400;
    
    public Hook()
    {
        super(EGameObjectType.eGOT_Player, 0);
        Texture hookPic = new Texture(ResourceManager.GetInstance().LoadResource("hook.JPG", false));
        hookPic.setWrap(TextureWrap.ClampToEdge, TextureWrap.ClampToEdge); 
        AddRenderUnit(hookPic);
        
        try
        {            
            GetFSM().AddState("Rotate",this);
            GetFSM().AddState("Eject", this);
            GetFSM().AddState("Return", this);
            GetFSM().AddState("Idle", this);
            GetFSM().InitState("Rotate");
        } catch (SecurityException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        SetPhysicsCallback(this, "Collide");
        SetWorldPos(GetRotateOrigin());
    }
    
    
    /// FSM - Rotate
    public void Rotate_Enter()
    {
        m_physElem.SetVelocity(0);
    }
    public void Rotate_Update()
    {
        ///Try to switch
        GetFSM().SwitchState(Gdx.input.isTouched(), "Eject");
        
        ///calculate pos.
        Vector2 initDir = new Vector2(0, 1);
        
        if (m_currentDegree > m_maxDegree || m_currentDegree < -m_maxDegree)
        {
            m_curRotateDirFactor *= -1;
        }
        m_currentDegree += GetRotateSpeed() * m_curRotateDirFactor * GameObjectManager.GetInstance().GetDeltaTime();
        initDir.mul(m_rotateRadius);
        initDir.rotate(m_currentDegree);
        initDir.mul(-1);
        Vector2 curPos = new Vector2();
        curPos.set(GetRotateOrigin());
        curPos.add(initDir);
        
        SetWorldPos(curPos);
    }
    public void Rotate_Exit()
    {
        
    }
    
    /// FSM - Eject
    public void Eject_Enter()
    {
        m_physElem.SetVelocity(m_ejectSpeed * 2);
        Vector2 currentDir = new Vector2();
        currentDir.set(GetRelativePos());
        currentDir.sub(GetRotateOrigin());
        m_physElem.SetDir(currentDir);
    }
    public void Eject_Update()
    {       
      ///Try to switch
        Vector2 deltaVec = new Vector2();
        deltaVec.set(GetWorldPos());
        deltaVec.sub(GetRotateOrigin());
        boolean outOfRange = (deltaVec.len() > m_ejectLength);
        GetFSM().SwitchState(outOfRange, "Return");
    }
    public void Eject_Exit()
    {
        
    }
    
    /// FSM - Return
    public void Return_Enter()
    {
        Vector2 backDir = new Vector2();
        backDir.set(m_physElem.GetDir());
        backDir.mul(-1);
        m_physElem.SetDir(backDir);
        m_physElem.SetVelocity(m_ejectSpeed);        
    }
    public void Return_Update()
    {
      ///Try to switch
        Vector2 deltaVec = new Vector2();
        deltaVec.set(GetWorldPos());
        deltaVec.sub(GetRotateOrigin());
        //Add a distance of delta time to avoid speed is too fast and get through.
        boolean outOfRange = (deltaVec.len() <= m_rotateRadius + GetDeltaTime() * m_physElem.GetVelocity() * 1.5);
        GetFSM().SwitchState(outOfRange, "Rotate");
    }
    public void Return_Exit()
    {
        
    }
    
    /// FSM - Idle
    public void Idle_Enter()
    {
        
    }
    public void Idle_Update()
    {
        
    }
    public void Idle_Exit()
    {
        
    }
    
    /// Collide Callback
    public void Collide_Enter(PhysicsElement physElem)
    {
        String info = String.format("enter collide\n");
        Log.d("CollideEnter", info);
    }
    public void Collide_Update(PhysicsElement physElem)
    {
        String info = String.format("Update collide\n");
        Log.d("CollideUpdate", info);
    }
    public void Collide_Exit(PhysicsElement physElem)
    {
        String info = String.format("Exit collide\n");
        Log.d("CollideExit", info);
    }


    public void SetRotateOrigin(Vector2 m_rotateOrigin)
    {
        this.m_rotateOrigin = m_rotateOrigin;
    }
    
    public void SetRotateOrigin(float x, float y)
    {
        this.m_rotateOrigin.x = x;
        this.m_rotateOrigin.y = y;
    }

    public Vector2 GetRotateOrigin()
    {
        return m_rotateOrigin;
    }


    public void SetRotateSpeed(float m_rotateSpeed)
    {
        this.m_rotateSpeed = m_rotateSpeed;
    }


    public float GetRotateSpeed()
    {
        return m_rotateSpeed;
    }

}
